#include "stdafx.h"
#include "Missile.h"

#include "AfterBurnerClone.h"
#include "../Framework/ContentManager.h"

namespace MyGame {

Missile::Missile(Game* game) : Flying(game) {
    this->explosionSound = NULL;
    this->flightSound = NULL;
    this->SetDirection(D3DXVECTOR3(0, 0, 1));
    this->SetMaxSpeed(20);
    this->SetMinSpeed(0);
    this->SetSpeed(20);
    this->target = NULL;
    this->SetTurnSpeed(3);
    this->SetScale(D3DXVECTOR3(0.5f, 0.5f, 0.5f));
    this->SetMeshFile("AA-10.x");
    this->SetEffectFile("PhongShader.fx");
    this->SetModelDirection(D3DXVECTOR3(0, 0, 1));
    this->particleEmitter = new ParticleEmitter(game);
    this->particleEmitter->SetBeginScale(D3DXVECTOR3(0.1f, 0.1f, 0.1f));
    this->particleEmitter->SetEndScale(D3DXVECTOR3(1, 1, 1));
    this->particleEmitter->SetParticleSystem(((AfterBurnerClone*)game)->GetParticleSystem());
    this->particleEmitter->SetGravity(D3DXVECTOR3(0, 0.5, 0));
    this->particleEmitter->SetParticleLife(0.5);
    this->particleEmitter->SetPeriod(0.01f);
    this->SetUsesFuel(true);
}

Missile::~Missile(void) {
    d3d::Delete(this->explosionSound);
    d3d::Delete(this->flightSound);
    d3d::Delete(this->particleEmitter);
}

void Missile::SetPosition(D3DXVECTOR3 val) {
    __super::SetPosition(val);
    this->particleEmitter->SetPosition(val);
}

Jet* Missile::GetTarget() const {
    return this->target;
}

void Missile::SetTarget(Jet* val) {
    this->target = val;
}

void Missile::Draw(FLOAT timeDelta) {
    D3DXVECTOR3 vLightDir = D3DXVECTOR3(1, 1, 1);
    D3DXVec3Normalize(&vLightDir, &vLightDir);
    D3DXCOLOR vLightDiffuse = D3DXCOLOR(1, 1, 1, 1);
    this->effect->SetValue("g_LightDir", &vLightDir, sizeof(D3DXVECTOR3));
    this->effect->SetValue("g_LightDiffuse", &vLightDiffuse, sizeof(D3DXCOLOR)) ;

    D3DXMATRIX mWorld = this->GetWorldMatrix();
    D3DXMATRIX mWorldViewProjection = mWorld * this->GetGame()->GetCamera()->GetViewMatrix() * this->GetGame()->GetCamera()->GetProjectionMatrix();
    this->effect->SetMatrix("g_mWorldViewProjection", &mWorldViewProjection) ;
    this->effect->SetMatrix("g_mWorld", &mWorld) ;
    this->effect->SetTechnique("Phong_Shader");

    D3DXCOLOR colorMtrlAmbient(0.1f, 0.1f, 0.1f, 1.0f);
    D3DXCOLOR colorMtrlDiffuse(1.0f, 1.0f, 1.0f, 1.0f);
    D3DXCOLOR colorMtrlSpecular(1.0f, 1.0f, 1.0f, 1);

    this->effect->SetValue("g_MaterialAmbientColor", &colorMtrlAmbient, sizeof(D3DXCOLOR));
    this->effect->SetValue("g_MaterialDiffuseColor", &colorMtrlDiffuse, sizeof(D3DXCOLOR));
    this->effect->SetValue("g_MaterialSpecularColor", &colorMtrlSpecular, sizeof(D3DXCOLOR));

    __super::Draw(timeDelta);
}

void Missile::Initialize() {
    __super::Initialize();

    this->particleEmitter->SetEffect(this->particleEmitter->GetParticleSystem()->GetSmoke());
}

void Missile::LoadContent() {
    __super::LoadContent();

    this->mesh->GetTextures()->clear();
    this->mesh->GetTextures()->push_back(this->GetGame()->GetContentManager()->LoadTexture("Empty.png"));

    this->explosionSound = this->GetGame()->GetContentManager()->LoadSound("Explosion.wav");
    this->flightSound = this->GetGame()->GetContentManager()->LoadSound("Jet.wav");
    if (this->flightSound != NULL) {
        D3DXVECTOR3 pos = this->GetPosition();
        this->flightSound->GetBuffer3D()->SetPosition(pos.x, pos.y, pos.z, DS3D_DEFERRED);
        this->flightSound->GetBuffer()->SetCurrentPosition(0);
        this->flightSound->GetBuffer()->Play(0, 0, DSBPLAY_LOOPING);
    }
}

void Missile::Update(FLOAT timeDelta) {
    if (this->GetState() == FLYINGSTATE_DYING) {
        return;
    }

    if (this->target != NULL) {
        d3d::BoundingBox* bb = this->target->GetBoundingBox();
        D3DXVECTOR3 targetPos = ((bb->_max - bb->_min) / 2) + bb->_min;
        D3DXVECTOR3 targetDirection = targetPos - this->GetPosition();
        D3DXVec3Normalize(&targetDirection, &targetDirection);

        FLOAT targetAngle = acos(D3DXVec3Dot(&this->GetDirection(), &targetDirection));
        FLOAT t = this->GetTurnSpeed() * timeDelta;
        if (targetAngle > t) {
            targetAngle = t;
        }

        D3DXVECTOR3 turnAxis;
        D3DXVec3Cross(&turnAxis, &targetDirection, &this->GetDirection());
        D3DXMATRIX turnMatrix;
        D3DXMatrixRotationAxis(&turnMatrix, &turnAxis, -targetAngle);
        D3DXVECTOR3 newDirection;
        D3DXVec3TransformCoord(&newDirection, &this->GetDirection(), &turnMatrix);
        this->SetDirection(newDirection);
    }

    FLOAT angle = -acos(D3DXVec3Dot(&this->GetDirection(), &this->GetModelDirection()));

    D3DXVECTOR3 axis;
    D3DXVec3Cross(&axis, &this->GetDirection(), &this->GetModelDirection());
    D3DXVec3Normalize(&axis, &axis);

    if (fabs(angle) - D3DX_PI < 0.0001 && D3DXVec3Length(&axis) < 0.99) {
        axis = D3DXVECTOR3(1, 0, 0);
    }

    D3DXMatrixRotationAxis(&this->rotationMatrix, &axis, angle);
    this->worldMatrixNeedsUpdate = true;
    this->boundingBoxNeedsUpdate = true;

    __super::Update(timeDelta);

    D3DXVECTOR3 part = this->GetModelDirection();
    D3DXVec3TransformCoord(&part, &part, &this->rotationMatrix);
    this->particleEmitter->SetPosition(this->GetPosition() - part / 2);
    this->particleEmitter->Update(timeDelta);

    if (this->flightSound != NULL) {
        D3DXVECTOR3 pos = this->GetPosition();
        this->flightSound->GetBuffer3D()->SetPosition(pos.x, pos.y, pos.z, DS3D_DEFERRED);
    }
}

}
